/*!
 * \file test_wts_cmp_helper.cpp
 * \project WonderTrader
 * 
 * \brief WTSCmpHelper数据压缩辅助工具测试套件
 * 
 * \details 测试WTSCmpHelper类的各种功能，包括：
 *          - ZSTD压缩和解压缩
 *          - 不同压缩级别测试
 *          - 各种数据类型压缩
 *          - 压缩比和性能测试
 *          - 错误处理和边界条件
 *          - 大数据量压缩测试
 */

#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "../../src/WTSUtils/WTSCmpHelper.hpp"
#include <string>
#include <vector>
#include <random>
#include <chrono>
#include <thread>
#include <atomic>
#include <cstring>
#include <limits>
#include <cmath>

/*!
 * \brief WTSCmpHelper压缩工具测试套件
 * 
 * \details 全面测试WTSCmpHelper的压缩和解压缩功能，包括：
 *          - 基本压缩解压缩操作
 *          - 不同压缩级别效果
 *          - 各种数据类型处理
 *          - 性能和压缩比测试
 *          - 异常处理验证
 */
class WTSCmpHelperTest : public ::testing::Test {
protected:
    void SetUp() override {
        // 测试前准备
        test_string = "Hello, WTSCmpHelper! This is a test string for compression.";
        test_chinese = "你好，这是一个中文测试字符串，用于测试压缩功能。包含各种中文字符：，。！？";
        
        // 创建重复数据（高压缩比）
        repetitive_data = std::string(1000, 'A') + std::string(1000, 'B') + std::string(1000, 'C');
        
        // 创建随机数据（低压缩比）
        generateRandomData();
        
        // 创建二进制数据
        generateBinaryData();
    }
    
    void TearDown() override {
        // 测试后清理
    }
    
    void generateRandomData() {
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_int_distribution<> dis(0, 255);
        
        random_data.resize(5000);
        for (size_t i = 0; i < random_data.size(); ++i) {
            random_data[i] = static_cast<char>(dis(gen));
        }
    }
    
    void generateBinaryData() {
        binary_data.resize(2048);
        for (size_t i = 0; i < binary_data.size(); ++i) {
            binary_data[i] = static_cast<char>(i % 256);
        }
    }
    
    // 测试数据
    std::string test_string;
    std::string test_chinese;
    std::string repetitive_data;
    std::string random_data;
    std::string binary_data;
};

// ========== 基本功能测试 ==========

/*!
 * \brief 测试基本压缩和解压缩
 */
TEST_F(WTSCmpHelperTest, TestBasicCompressDecompress) {
    // 压缩测试字符串
    std::string compressed = WTSCmpHelper::compress_data(
        test_string.c_str(), test_string.length());
    
    // 验证压缩结果
    EXPECT_FALSE(compressed.empty());
    EXPECT_NE(compressed, test_string); // 压缩后应该不同
    
    // 解压缩
    std::string decompressed = WTSCmpHelper::uncompress_data(
        compressed.c_str(), compressed.length());
    
    // 验证解压缩结果
    EXPECT_EQ(decompressed, test_string);
}

/*!
 * \brief 测试中文字符串压缩
 */
TEST_F(WTSCmpHelperTest, TestChineseStringCompression) {
    // 压缩中文字符串
    std::string compressed = WTSCmpHelper::compress_data(
        test_chinese.c_str(), test_chinese.length());
    
    EXPECT_FALSE(compressed.empty());
    
    // 解压缩并验证
    std::string decompressed = WTSCmpHelper::uncompress_data(
        compressed.c_str(), compressed.length());
    
    EXPECT_EQ(decompressed, test_chinese);
}

/*!
 * \brief 测试空字符串处理
 */
TEST_F(WTSCmpHelperTest, TestEmptyString) {
    std::string empty_string = "";
    
    // 压缩空字符串
    std::string compressed = WTSCmpHelper::compress_data(
        empty_string.c_str(), empty_string.length());
    
    // 解压缩
    std::string decompressed = WTSCmpHelper::uncompress_data(
        compressed.c_str(), compressed.length());
    
    EXPECT_EQ(decompressed, empty_string);
}

/*!
 * \brief 测试单字符压缩
 */
TEST_F(WTSCmpHelperTest, TestSingleCharacter) {
    std::string single_char = "A";
    
    std::string compressed = WTSCmpHelper::compress_data(
        single_char.c_str(), single_char.length());
    
    std::string decompressed = WTSCmpHelper::uncompress_data(
        compressed.c_str(), compressed.length());
    
    EXPECT_EQ(decompressed, single_char);
}

// ========== 压缩级别测试 ==========

/*!
 * \brief 测试不同压缩级别
 */
TEST_F(WTSCmpHelperTest, TestCompressionLevels) {
    std::vector<uint32_t> levels = {1, 3, 6, 9, 12, 15, 19, 22};
    std::vector<std::string> compressed_results;
    
    // 测试不同压缩级别
    for (uint32_t level : levels) {
        std::string compressed = WTSCmpHelper::compress_data(
            repetitive_data.c_str(), repetitive_data.length(), level);
        
        compressed_results.push_back(compressed);
        
        // 验证解压缩正确性
        std::string decompressed = WTSCmpHelper::uncompress_data(
            compressed.c_str(), compressed.length());
        
        EXPECT_EQ(decompressed, repetitive_data);
    }
    
    // 验证压缩级别越高，压缩后数据越小（对于重复数据）
    for (size_t i = 1; i < compressed_results.size(); ++i) {
        // 高级别压缩应该产生更小或相等的结果
        EXPECT_LE(compressed_results[i].size(), compressed_results[i-1].size() * 1.1);
    }
}

/*!
 * \brief 测试压缩级别边界值
 */
TEST_F(WTSCmpHelperTest, TestCompressionLevelBoundaries) {
    // 测试最低级别
    std::string compressed_min = WTSCmpHelper::compress_data(
        test_string.c_str(), test_string.length(), 1);
    
    // 测试最高级别
    std::string compressed_max = WTSCmpHelper::compress_data(
        test_string.c_str(), test_string.length(), 22);
    
    // 两种压缩都应该成功
    EXPECT_FALSE(compressed_min.empty());
    EXPECT_FALSE(compressed_max.empty());
    
    // 验证解压缩
    std::string decompressed_min = WTSCmpHelper::uncompress_data(
        compressed_min.c_str(), compressed_min.length());
    std::string decompressed_max = WTSCmpHelper::uncompress_data(
        compressed_max.c_str(), compressed_max.length());
    
    EXPECT_EQ(decompressed_min, test_string);
    EXPECT_EQ(decompressed_max, test_string);
}

// ========== 数据类型测试 ==========

/*!
 * \brief 测试二进制数据压缩
 */
TEST_F(WTSCmpHelperTest, TestBinaryDataCompression) {
    std::string compressed = WTSCmpHelper::compress_data(
        binary_data.c_str(), binary_data.length());
    
    EXPECT_FALSE(compressed.empty());
    
    std::string decompressed = WTSCmpHelper::uncompress_data(
        compressed.c_str(), compressed.length());
    
    EXPECT_EQ(decompressed, binary_data);
}

/*!
 * \brief 测试结构体数据压缩
 */
TEST_F(WTSCmpHelperTest, TestStructDataCompression) {
    // 定义测试结构体
    struct TestStruct {
        int id;
        double price;
        char symbol[16];
        uint64_t timestamp;
    };
    
    // 创建测试数据
    std::vector<TestStruct> test_data;
    for (int i = 0; i < 100; ++i) {
        TestStruct item;
        item.id = i;
        item.price = 100.0 + i * 0.01;
        snprintf(item.symbol, sizeof(item.symbol), "SYM%03d", i);
        item.timestamp = 1600000000 + i;
        test_data.push_back(item);
    }
    
    // 压缩结构体数组
    std::string compressed = WTSCmpHelper::compress_data(
        test_data.data(), test_data.size() * sizeof(TestStruct));
    
    EXPECT_FALSE(compressed.empty());
    
    // 解压缩
    std::string decompressed = WTSCmpHelper::uncompress_data(
        compressed.c_str(), compressed.length());
    
    // 验证数据完整性
    EXPECT_EQ(decompressed.size(), test_data.size() * sizeof(TestStruct));
    
    const TestStruct* recovered_data = 
        reinterpret_cast<const TestStruct*>(decompressed.c_str());
    
    for (size_t i = 0; i < test_data.size(); ++i) {
        EXPECT_EQ(recovered_data[i].id, test_data[i].id);
        EXPECT_DOUBLE_EQ(recovered_data[i].price, test_data[i].price);
        EXPECT_STREQ(recovered_data[i].symbol, test_data[i].symbol);
        EXPECT_EQ(recovered_data[i].timestamp, test_data[i].timestamp);
    }
}

/*!
 * \brief 测试数值数组压缩
 */
TEST_F(WTSCmpHelperTest, TestNumericArrayCompression) {
    // 创建数值数组
    std::vector<double> prices;
    for (int i = 0; i < 1000; ++i) {
        prices.push_back(100.0 + sin(i * 0.1) * 10.0); // 模拟价格波动
    }
    
    // 压缩数值数组
    std::string compressed = WTSCmpHelper::compress_data(
        prices.data(), prices.size() * sizeof(double));
    
    EXPECT_FALSE(compressed.empty());
    
    // 解压缩
    std::string decompressed = WTSCmpHelper::uncompress_data(
        compressed.c_str(), compressed.length());
    
    // 验证数据
    EXPECT_EQ(decompressed.size(), prices.size() * sizeof(double));
    
    const double* recovered_prices = 
        reinterpret_cast<const double*>(decompressed.c_str());
    
    for (size_t i = 0; i < prices.size(); ++i) {
        EXPECT_DOUBLE_EQ(recovered_prices[i], prices[i]);
    }
}

// ========== 性能和压缩比测试 ==========

/*!
 * \brief 测试压缩比
 */
TEST_F(WTSCmpHelperTest, TestCompressionRatio) {
    // 测试重复数据的压缩比
    std::string compressed_repetitive = WTSCmpHelper::compress_data(
        repetitive_data.c_str(), repetitive_data.length(), 6);
    
    double repetitive_ratio = static_cast<double>(compressed_repetitive.length()) / 
                             repetitive_data.length();
    
    // 重复数据应该有很好的压缩比
    EXPECT_LT(repetitive_ratio, 0.1); // 压缩比应该小于10%
    
    // 测试随机数据的压缩比
    std::string compressed_random = WTSCmpHelper::compress_data(
        random_data.c_str(), random_data.length(), 6);
    
    double random_ratio = static_cast<double>(compressed_random.length()) / 
                         random_data.length();
    
    // 随机数据压缩比较差
    EXPECT_GT(random_ratio, 0.8); // 压缩比应该大于80%
    
    std::cout << "重复数据压缩比: " << (repetitive_ratio * 100) << "%" << std::endl;
    std::cout << "随机数据压缩比: " << (random_ratio * 100) << "%" << std::endl;
}

/*!
 * \brief 测试压缩性能
 */
TEST_F(WTSCmpHelperTest, TestCompressionPerformance) {
    const int iterations = 100;
    std::string test_data = repetitive_data + random_data;
    
    // 测试压缩性能
    auto start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < iterations; ++i) {
        std::string compressed = WTSCmpHelper::compress_data(
            test_data.c_str(), test_data.length(), 6);
        (void)compressed; // 避免编译器优化
    }
    auto compress_duration = std::chrono::high_resolution_clock::now() - start;
    
    // 先压缩一次用于解压缩测试
    std::string compressed_for_test = WTSCmpHelper::compress_data(
        test_data.c_str(), test_data.length(), 6);
    
    // 测试解压缩性能
    start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < iterations; ++i) {
        std::string decompressed = WTSCmpHelper::uncompress_data(
            compressed_for_test.c_str(), compressed_for_test.length());
        (void)decompressed; // 避免编译器优化
    }
    auto decompress_duration = std::chrono::high_resolution_clock::now() - start;
    
    auto compress_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
        compress_duration).count();
    auto decompress_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
        decompress_duration).count();
    
    std::cout << "压缩性能 (" << iterations << " 次): " << compress_ms << "ms" << std::endl;
    std::cout << "解压缩性能 (" << iterations << " 次): " << decompress_ms << "ms" << std::endl;
    
    // 性能测试不应该失败，只是记录结果（允许0毫秒，因为操作可能很快）
    EXPECT_GE(compress_ms, 0);
    EXPECT_GE(decompress_ms, 0);
}

// ========== 大数据量测试 ==========

/*!
 * \brief 测试大数据量压缩
 */
TEST_F(WTSCmpHelperTest, TestLargeDataCompression) {
    // 创建大数据（1MB）
    std::string large_data;
    large_data.reserve(1024 * 1024);
    
    // 混合重复和随机数据
    for (int i = 0; i < 1024; ++i) {
        large_data += repetitive_data.substr(0, 512);
        large_data += random_data.substr(0, 512);
    }
    
    // 压缩大数据
    auto start = std::chrono::high_resolution_clock::now();
    std::string compressed = WTSCmpHelper::compress_data(
        large_data.c_str(), large_data.length(), 6);
    auto compress_time = std::chrono::high_resolution_clock::now() - start;
    
    EXPECT_FALSE(compressed.empty());
    
    // 解压缩大数据
    start = std::chrono::high_resolution_clock::now();
    std::string decompressed = WTSCmpHelper::uncompress_data(
        compressed.c_str(), compressed.length());
    auto decompress_time = std::chrono::high_resolution_clock::now() - start;
    
    // 验证数据完整性
    EXPECT_EQ(decompressed, large_data);
    
    // 计算压缩比
    double compression_ratio = static_cast<double>(compressed.length()) / 
                              large_data.length();
    
    auto compress_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
        compress_time).count();
    auto decompress_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
        decompress_time).count();
    
    std::cout << "大数据压缩 (1MB):" << std::endl;
    std::cout << "  原始大小: " << large_data.length() << " 字节" << std::endl;
    std::cout << "  压缩后大小: " << compressed.length() << " 字节" << std::endl;
    std::cout << "  压缩比: " << (compression_ratio * 100) << "%" << std::endl;
    std::cout << "  压缩时间: " << compress_ms << "ms" << std::endl;
    std::cout << "  解压缩时间: " << decompress_ms << "ms" << std::endl;
}

// ========== 并发测试 ==========

/*!
 * \brief 测试多线程压缩
 */
TEST_F(WTSCmpHelperTest, TestMultiThreadCompression) {
    const int num_threads = 4;
    const int iterations_per_thread = 50;
    std::vector<std::thread> threads;
    std::atomic<int> success_count(0);
    std::atomic<int> error_count(0);
    
    // 启动多个线程同时进行压缩解压缩
    for (int t = 0; t < num_threads; ++t) {
        threads.emplace_back([&, t]() {
            for (int i = 0; i < iterations_per_thread; ++i) {
                try {
                    // 创建线程特定的测试数据
                    std::string thread_data = test_string + std::to_string(t) + 
                                            std::to_string(i);
                    
                    // 压缩
                    std::string compressed = WTSCmpHelper::compress_data(
                        thread_data.c_str(), thread_data.length(), 6);
                    
                    // 解压缩
                    std::string decompressed = WTSCmpHelper::uncompress_data(
                        compressed.c_str(), compressed.length());
                    
                    // 验证
                    if (decompressed == thread_data) {
                        success_count++;
                    } else {
                        error_count++;
                    }
                } catch (...) {
                    error_count++;
                }
            }
        });
    }
    
    // 等待所有线程完成
    for (auto& thread : threads) {
        thread.join();
    }
    
    // 验证结果
    EXPECT_EQ(success_count.load(), num_threads * iterations_per_thread);
    EXPECT_EQ(error_count.load(), 0);
    
    std::cout << "多线程测试结果:" << std::endl;
    std::cout << "  成功次数: " << success_count.load() << std::endl;
    std::cout << "  错误次数: " << error_count.load() << std::endl;
}

// ========== 错误处理测试 ==========

/*!
 * \brief 测试无效数据解压缩
 */
TEST_F(WTSCmpHelperTest, TestInvalidDataDecompression) {
    // 测试无效压缩数据
    std::string invalid_data = "This is not compressed data";
    
    // 解压缩无效数据应该抛出异常（根据实际行为调整异常类型）
    EXPECT_THROW({
        WTSCmpHelper::uncompress_data(invalid_data.c_str(), invalid_data.length());
    }, std::length_error);
}

/*!
 * \brief 测试损坏的压缩数据
 */
TEST_F(WTSCmpHelperTest, TestCorruptedCompressedData) {
    // 先正常压缩
    std::string compressed = WTSCmpHelper::compress_data(
        test_string.c_str(), test_string.length());
    
    // 损坏压缩数据（更严重的损坏）
    if (!compressed.empty()) {
        // 完全破坏压缩数据的头部
        for (size_t i = 0; i < std::min(compressed.length(), size_t(10)); ++i) {
            compressed[i] = static_cast<char>(0xFF);
        }
    }
    
    // 尝试解压缩损坏的数据
    try {
        std::string result = WTSCmpHelper::uncompress_data(compressed.c_str(), compressed.length());
        // 如果没有抛出异常，至少验证结果不等于原始数据
        EXPECT_NE(result, test_string);
        std::cout << "损坏数据解压缩未抛出异常，但结果不匹配原始数据" << std::endl;
    } catch (const std::exception& e) {
        // 如果抛出异常，这是预期的行为
        std::cout << "损坏数据解压缩抛出异常: " << e.what() << std::endl;
        SUCCEED(); // 抛出异常是可接受的行为
    }
}

/*!
 * \brief 测试边界条件
 */
TEST_F(WTSCmpHelperTest, TestBoundaryConditions) {
    // 测试非常小的数据
    std::string tiny_data = "x";
    std::string compressed_tiny = WTSCmpHelper::compress_data(
        tiny_data.c_str(), tiny_data.length());
    std::string decompressed_tiny = WTSCmpHelper::uncompress_data(
        compressed_tiny.c_str(), compressed_tiny.length());
    EXPECT_EQ(decompressed_tiny, tiny_data);
    
    // 测试包含空字符的数据
    std::string data_with_nulls = "Hello\0World\0Test";
    data_with_nulls.resize(17); // 确保包含空字符
    
    std::string compressed_nulls = WTSCmpHelper::compress_data(
        data_with_nulls.c_str(), data_with_nulls.length());
    std::string decompressed_nulls = WTSCmpHelper::uncompress_data(
        compressed_nulls.c_str(), compressed_nulls.length());
    
    EXPECT_EQ(decompressed_nulls.length(), data_with_nulls.length());
    EXPECT_EQ(decompressed_nulls, data_with_nulls);
}

/*!
 * \brief 测试内存使用
 */
TEST_F(WTSCmpHelperTest, TestMemoryUsage) {
    // 测试多次压缩解压缩不会内存泄漏
    for (int i = 0; i < 1000; ++i) {
        std::string test_data = test_string + std::to_string(i);
        
        std::string compressed = WTSCmpHelper::compress_data(
            test_data.c_str(), test_data.length());
        
        std::string decompressed = WTSCmpHelper::uncompress_data(
            compressed.c_str(), compressed.length());
        
        EXPECT_EQ(decompressed, test_data);
    }
    
    // 如果有内存泄漏，这个测试可能会失败或者系统内存使用会异常增长
    SUCCEED(); // 如果能执行到这里说明没有明显的内存泄漏
} 